package com.second.app.thread.线程基础.day05;


/**
 * @Author GYZ
 * @Date 2023/11/23
 * <pre>
 *   静态同步方法&&synchronized(class)
 *        案例1： 看运行效果，并没有什么特别的地方，都是同步的效果。
 *               和将synchronized关键字加到非static方法上使用的效果是一样的。
 *               但是其实本质上还是有不同的，synchronized加到static静态方法上是给class类上锁,而synchronized关键字加到非static静态方法上是给对象上锁
 *               为了验证不是同一个锁，看下案例2
 *        案例2：线程A,B共用类锁。线程C用的对象锁.
 *
 *        案例3：数据类型String的常量池特性.
 *             两个线程持有相同的锁，所以造成B线程不能执行。这就是String常量池的问题，因此在大多数情况下
 *             同步synchronized代码块都不使用String作为锁对象，而改用其他。比如new Object()实例化一个Object对象
 *             但是它不放入缓存中
 *        案例4：同步synchronized方法无限等待与解决
 *              同步方法容易造成死循环,比如线程B永远得不到运行的机会。
 *              使用同步块解决问题，如案例5，每个线程使用不同的锁对象，互不影响。
 * </pre>
 */

// 案例5
class Service05 {
    Object object1 = new Object();

    public void methodA() {
        synchronized (object1) {
            System.out.println("methodA begin");
            boolean isContinueRun = true;
            while (isContinueRun) {
            }
            System.out.println("methodA end");
        }
    }

    Object object2 = new Object();

    public void methodB() {
        synchronized (object2) {
            System.out.println("methodB begin");
            System.out.println("methodB end");
        }
    }
}

class Test05 {

    public static void main(String[] args) {
        class Thread01 extends Thread {
            private Service05 service05;

            public Thread01(Service05 service05) {
                this.service05 = service05;
            }

            @Override
            public void run() {
                service05.methodA();
            }
        }
        class Thread02 extends Thread {
            private Service05 service05;

            public Thread02(Service05 service05) {
                this.service05 = service05;
            }

            @Override
            public void run() {
                service05.methodB();
            }
        }
        Service05 service05 = new Service05();
        Thread01 thread01 = new Thread01(service05);
        thread01.setName("A");
        thread01.start();

        Thread02 thread02 = new Thread02(service05);
        thread02.setName("B");
        thread02.start();
    }

}

//案例4

class Service04 {
    synchronized public void methodA() {
        System.out.println("methodA begin");
        boolean isContinueRun = true;
        while (isContinueRun) {
        }
        System.out.println("methodA end");
    }

    synchronized public void methodB() {
        System.out.println("methodB begin");
        System.out.println("methodB end");
    }
}

//案例4
class Test04 {

    public static void main(String[] args) {
        class Thread01 extends Thread {
            private Service04 service04;

            public Thread01(Service04 service04) {
                this.service04 = service04;
            }

            @Override
            public void run() {
                service04.methodA();
            }
        }
        class Thread02 extends Thread {
            private Service04 service04;

            public Thread02(Service04 service04) {
                this.service04 = service04;
            }

            @Override
            public void run() {
                service04.methodA();
            }
        }
        Service04 service04 = new Service04();
        Thread01 thread01 = new Thread01(service04);
        thread01.setName("A");
        thread01.start();

        Thread02 thread02 = new Thread02(service04);
        thread02.setName("B");
        thread02.start();
    }

}


//案例3
class Service03 {
    public static void print(Object stringParam) {
        try {
            synchronized (stringParam) {
                while (true) {
                    System.out.println(Thread.currentThread().getName());
                    Thread.sleep(1000);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


class Test03 {

    public static void main(String[] args) {
        class Thread01 extends Thread {
            private Service03 service03;

            public Thread01(Service03 service03) {
                this.service03 = service03;
            }

            @Override
            public void run() {
                service03.print(new Object());
//                service03.print("AA");
            }
        }
        class Thread02 extends Thread {
            private Service03 service03;

            public Thread02(Service03 service03) {
                this.service03 = service03;
            }

            @Override
            public void run() {
//                service03.print("AA");
                service03.print(new Object());
            }
        }
        Service03 service03 = new Service03();
        Thread01 thread01 = new Thread01(service03);
        thread01.setName("A");
        thread01.start();

        Thread02 thread02 = new Thread02(service03);
        thread02.setName("B");
        thread02.start();
    }

}


//案例2
class Service02 {
    synchronized public static void printA() {
        try {
            System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printA");
            Thread.sleep(3000);
            System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printA");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized public static void printB() {
        System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printB");
        System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printB");
    }

    synchronized public void printC() {
        System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printC");
        System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printC");
    }
}

//案例2
class Test02 {
    public static void main(String[] args) {
        class Thread01 extends Thread {
            private Service02 service02;

            public Thread01(Service02 service02) {
                this.service02 = service02;
            }

            @Override
            public void run() {
                service02.printA();
            }
        }
        class Thread02 extends Thread {
            private Service02 service02;

            public Thread02(Service02 service02) {
                this.service02 = service02;
            }

            @Override
            public void run() {
                service02.printB();
            }
        }
        class Thread03 extends Thread {

            private Service02 service02;

            public Thread03(Service02 service02) {
                this.service02 = service02;
            }

            @Override
            public void run() {
                service02.printC();
            }
        }
        Service02 service02 = new Service02();
        Thread01 thread01 = new Thread01(service02);
        thread01.setName("A");
        thread01.start();

        Thread02 thread02 = new Thread02(service02);
        thread02.setName("B");
        thread02.start();

        Thread03 thread03 = new Thread03(service02);
        thread03.setName("C");
        thread03.start();
    }
}


//案例1
public class Service {
    synchronized public static void printA() {
        try {
            System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printA");
            Thread.sleep(3000);
            System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printA");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    synchronized public static void printB() {
        try {
            System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printB");
            Thread.sleep(3000);
            System.out.println("线程名称为：" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printB");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


//案例1
class Test {
    public static void main(String[] args) {
        class Thread01 extends Thread {
            @Override
            public void run() {
                Service.printA();
            }
        }
        class Thread02 extends Thread {
            @Override
            public void run() {
                Service.printB();
            }
        }
        Thread01 thread01 = new Thread01();
        thread01.setName("A");
        thread01.start();

        Thread02 thread02 = new Thread02();
        thread02.setName("B");
        thread02.start();
    }
}
